package com.ruoyi.pos.service.impl;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.pos.domain.PosMenu;
import com.ruoyi.pos.mapper.PosMenuMapper;
import com.ruoyi.pos.service.IPosMenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * POS菜单配置Service业务层处理
 * 
 * @author Grand Pacific
 * @date 2024-01-01
 */
@Service
public class PosMenuServiceImpl implements IPosMenuService {
    
    private static final Logger logger = LoggerFactory.getLogger(PosMenuServiceImpl.class);

    @Autowired
    private PosMenuMapper posMenuMapper;

    /**
     * 查询POS菜单配置
     * 
     * @param menuId POS菜单配置主键
     * @return POS菜单配置
     */
    @Override
    public PosMenu selectPosMenuByMenuId(Long menuId) {
        logger.info("查询POS菜单配置, menuId: {}", menuId);
        
        try {
            PosMenu menu = posMenuMapper.selectPosMenuByMenuId(menuId);
            
            if (menu != null) {
                logger.info("查询POS菜单配置成功, menuId: {}, menuName: {}", menuId, menu.getMenuName());
            } else {
                logger.warn("POS菜单配置不存在, menuId: {}", menuId);
            }
            
            return menu;
        } catch (Exception e) {
            logger.error("查询POS菜单配置失败, menuId: {}, error: {}", menuId, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 查询POS菜单配置列表
     * 
     * @param posMenu POS菜单配置
     * @return POS菜单配置
     */
    @Override
    public List<PosMenu> selectPosMenuList(PosMenu posMenu) {
        logger.info("查询POS菜单配置列表, params: {}", posMenu);
        
        try {
            List<PosMenu> list = posMenuMapper.selectPosMenuList(posMenu);
            logger.info("查询POS菜单配置列表成功, 共 {} 条记录", list.size());
            return list;
        } catch (Exception e) {
            logger.error("查询POS菜单配置列表失败, error: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 新增POS菜单配置
     * 
     * @param posMenu POS菜单配置
     * @return 结果
     */
    @Override
    public int insertPosMenu(PosMenu posMenu) {
        logger.info("新增POS菜单配置, menuName: {}, menuCode: {}, menuType: {}", 
                posMenu.getMenuName(), posMenu.getMenuCode(), posMenu.getMenuType());
        
        try {
            int result = posMenuMapper.insertPosMenu(posMenu);
            
            if (result > 0) {
                logger.info("新增POS菜单配置成功, menuId: {}, menuName: {}", 
                        posMenu.getMenuId(), posMenu.getMenuName());
            } else {
                logger.warn("新增POS菜单配置失败, menuName: {}", posMenu.getMenuName());
            }
            
            return result;
        } catch (Exception e) {
            logger.error("新增POS菜单配置异常, menuName: {}, error: {}", 
                    posMenu.getMenuName(), e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 修改POS菜单配置
     * 
     * @param posMenu POS菜单配置
     * @return 结果
     */
    @Override
    public int updatePosMenu(PosMenu posMenu) {
        logger.info("修改POS菜单配置, menuId: {}, menuName: {}", 
                posMenu.getMenuId(), posMenu.getMenuName());
        
        try {
            int result = posMenuMapper.updatePosMenu(posMenu);
            
            if (result > 0) {
                logger.info("修改POS菜单配置成功, menuId: {}", posMenu.getMenuId());
            } else {
                logger.warn("修改POS菜单配置失败, menuId: {}", posMenu.getMenuId());
            }
            
            return result;
        } catch (Exception e) {
            logger.error("修改POS菜单配置异常, menuId: {}, error: {}", 
                    posMenu.getMenuId(), e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 批量删除POS菜单配置
     * 
     * @param menuIds 需要删除的POS菜单配置主键
     * @return 结果
     */
    @Override
    public int deletePosMenuByMenuIds(Long[] menuIds) {
        logger.info("批量删除POS菜单配置, menuIds: {}", (Object) menuIds);
        
        try {
            int result = posMenuMapper.deletePosMenuByMenuIds(menuIds);
            logger.info("批量删除POS菜单配置成功, 删除 {} 条记录", result);
            return result;
        } catch (Exception e) {
            logger.error("批量删除POS菜单配置异常, error: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 删除POS菜单配置信息
     * 
     * @param menuId POS菜单配置主键
     * @return 结果
     */
    @Override
    public int deletePosMenuByMenuId(Long menuId) {
        logger.info("删除POS菜单配置, menuId: {}", menuId);
        
        try {
            int result = posMenuMapper.deletePosMenuByMenuId(menuId);
            
            if (result > 0) {
                logger.info("删除POS菜单配置成功, menuId: {}", menuId);
            } else {
                logger.warn("删除POS菜单配置失败, menuId: {}", menuId);
            }
            
            return result;
        } catch (Exception e) {
            logger.error("删除POS菜单配置异常, menuId: {}, error: {}", menuId, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 根据设备信息获取可用菜单列表
     * 
     * @param deviceCode 设备编码
     * @param deviceType 设备类型
     * @return 菜单列表
     */
    @Override
    public List<PosMenu> selectDeviceMenus(String deviceCode, String deviceType) {
        logger.info("查询设备可用菜单, deviceCode: {}, deviceType: {}", deviceCode, deviceType);
        
        try {
            // 查询所有启用状态的菜单
            PosMenu query = new PosMenu();
            query.setStatus("0"); // 正常状态
            query.setVisible("0"); // 可见
            
            if (StringUtils.isNotEmpty(deviceType)) {
                query.setDeviceType(deviceType);
            }
            
            List<PosMenu> menus = posMenuMapper.selectDeviceMenus(query);
            
            // 构建菜单树
            List<PosMenu> menuTree = buildMenuTree(menus);
            
            logger.info("查询设备可用菜单成功, deviceCode: {}, 共 {} 个菜单项", 
                    deviceCode, menus.size());
            
            return menuTree;
        } catch (Exception e) {
            logger.error("查询设备可用菜单异常, deviceCode: {}, error: {}", 
                    deviceCode, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 构建菜单树形结构
     * 
     * @param menus 菜单列表
     * @return 菜单树
     */
    @Override
    public List<PosMenu> buildMenuTreeSelect(List<PosMenu> menus) {
        logger.debug("构建菜单树形结构, 菜单总数: {}", menus.size());
        
        try {
            List<PosMenu> tree = buildMenuTree(menus);
            logger.debug("构建菜单树形结构成功, 根节点数: {}", tree.size());
            return tree;
        } catch (Exception e) {
            logger.error("构建菜单树形结构异常, error: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 根据父级菜单ID查询子菜单
     * 
     * @param parentId 父级菜单ID
     * @return 子菜单列表
     */
    @Override
    public List<PosMenu> selectMenusByParentId(Long parentId) {
        logger.info("查询子菜单, parentId: {}", parentId);
        
        try {
            List<PosMenu> children = posMenuMapper.selectMenusByParentId(parentId);
            logger.info("查询子菜单成功, parentId: {}, 子菜单数: {}", parentId, children.size());
            return children;
        } catch (Exception e) {
            logger.error("查询子菜单异常, parentId: {}, error: {}", parentId, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 更新菜单状态
     * 
     * @param posMenu 菜单信息
     * @return 结果
     */
    @Override
    public int updatePosMenuStatus(PosMenu posMenu) {
        logger.info("更新菜单状态, menuId: {}, status: {}", posMenu.getMenuId(), posMenu.getStatus());
        
        try {
            int result = posMenuMapper.updatePosMenuStatus(posMenu);
            
            if (result > 0) {
                logger.info("更新菜单状态成功, menuId: {}", posMenu.getMenuId());
            } else {
                logger.warn("更新菜单状态失败, menuId: {}", posMenu.getMenuId());
            }
            
            return result;
        } catch (Exception e) {
            logger.error("更新菜单状态异常, menuId: {}, error: {}", 
                    posMenu.getMenuId(), e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 更新菜单排序
     * 
     * @param posMenu 菜单信息
     * @return 结果
     */
    @Override
    public int updatePosMenuOrder(PosMenu posMenu) {
        logger.info("更新菜单排序, menuId: {}, orderNum: {}", 
                posMenu.getMenuId(), posMenu.getOrderNum());
        
        try {
            int result = posMenuMapper.updatePosMenuOrder(posMenu);
            
            if (result > 0) {
                logger.info("更新菜单排序成功, menuId: {}", posMenu.getMenuId());
            } else {
                logger.warn("更新菜单排序失败, menuId: {}", posMenu.getMenuId());
            }
            
            return result;
        } catch (Exception e) {
            logger.error("更新菜单排序异常, menuId: {}, error: {}", 
                    posMenu.getMenuId(), e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 构建菜单树
     */
    private List<PosMenu> buildMenuTree(List<PosMenu> menus) {
        List<PosMenu> returnList = new ArrayList<>();
        List<Long> tempList = menus.stream().map(PosMenu::getMenuId).collect(Collectors.toList());
        
        for (PosMenu menu : menus) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(menu.getParentId())) {
                recursionFn(menus, menu);
                returnList.add(menu);
            }
        }
        
        if (returnList.isEmpty()) {
            returnList = menus;
        }
        
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<PosMenu> list, PosMenu t) {
        // 得到子节点列表
        List<PosMenu> childList = getChildList(list, t);
        t.setChildren(childList);
        
        for (PosMenu tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<PosMenu> getChildList(List<PosMenu> list, PosMenu t) {
        List<PosMenu> tlist = new ArrayList<>();
        Iterator<PosMenu> it = list.iterator();
        
        while (it.hasNext()) {
            PosMenu n = it.next();
            if (n.getParentId() != null && n.getParentId().longValue() == t.getMenuId().longValue()) {
                tlist.add(n);
            }
        }
        
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<PosMenu> list, PosMenu t) {
        return getChildList(list, t).size() > 0;
    }
}
